home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / shell / dialog-0.000 / dialog-0 / dialog-0.6c / mouse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-08-11  |  6.7 KB  |  273 lines

  1. /*
  2.  * mouse.c - mouse support for "dialog"
  3.  *
  4.  * Copyright 1994   rubini@ipvvis.unipv.it (Alessandro Rubini)
  5.  *
  6.  *   This program is free software; you can redistribute it and/or modify
  7.  *   it under the terms of the GNU General Public License as published by
  8.  *   the Free Software Foundation; either version 2 of the License, or
  9.  *   (at your option) any later version.
  10.  *
  11.  *   This program is distributed in the hope that it will be useful,
  12.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *   GNU General Public License for more details.
  15.  *
  16.  *   You should have received a copy of the GNU General Public License
  17.  *   along with this program; if not, write to the Free Software
  18.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  ********/
  20.  
  21. #include "dialog.h"
  22.  
  23. #include <gpm.h>
  24.  
  25. static Gpm_Connect connectInfo;
  26. static Gpm_Handler mouse_handler;
  27.  
  28. static int basex, basey;
  29.  
  30. typedef struct Region {
  31.     int x, y, X, Y, code;
  32.     struct Region *next;
  33. } Region;
  34.  
  35. static Region *regionList = NULL;
  36.  
  37. static struct bigRegion {
  38.     int x, y, X, Y;
  39.     int height, nitems;
  40.     int xth;
  41.     int step, mode;
  42. } bigRegion;            /* have a static one */
  43.  
  44. static int bigregionFlag = 0;    /* no bigRegion at startup */
  45.  
  46. /*==================== simple functions =============*/
  47.  
  48. void
  49. mouse_open (void)
  50. {
  51.     gpm_zerobased = gpm_visiblepointer = 1;
  52.     connectInfo.eventMask = ~0;
  53.     connectInfo.defaultMask = GPM_MOVE & GPM_HARD;
  54.     connectInfo.minMod = connectInfo.maxMod = 0;
  55.     Gpm_Open (&connectInfo, 0);
  56.     gpm_handler = mouse_handler;
  57. }
  58.  
  59. void
  60. mouse_close (void)
  61. {
  62.     Gpm_Close ();
  63. }
  64.  
  65. void
  66. mouse_setbase (int x, int y)
  67. {
  68.     basex = x;
  69.     basey = y;
  70. }
  71.  
  72. /*=========== region related functions =============*/
  73.  
  74. void
  75. mouse_mkbigregion (int y, int x, int height, int width, int nitems,
  76.            int th, int mode)
  77. {
  78.     bigRegion.x = basex + x;
  79.     bigRegion.X = basex + x + width;
  80.     bigRegion.y = basey + y;
  81.     bigRegion.Y = basey + y + height;
  82.     bigRegion.height = height - 3;
  83.     bigRegion.nitems = nitems;
  84.     bigRegion.xth = basex + th;
  85.     bigRegion.step = nitems > height ? nitems / height : 1;
  86.     if (mode == 2)        /* text box */
  87.     bigRegion.step = height - 3;
  88.     bigRegion.mode = mode;
  89.     bigregionFlag++;
  90. }
  91.  
  92. void
  93. mouse_mkregion (int y, int x, int height, int width, int code)
  94. {
  95.     Region *butPtr;
  96.  
  97.     butPtr = malloc (sizeof (Region));
  98.     if (!butPtr)
  99.     return;            /* WARN */
  100.     butPtr->y = basey + y;
  101.     butPtr->Y = basey + y + height;
  102.     butPtr->x = basex + x;
  103.     butPtr->X = basex + x + width;
  104.     butPtr->code = code;
  105.     butPtr->next = regionList;
  106.     regionList = butPtr;
  107. }
  108.  
  109. /*=================================================== the mouse handler ====*/
  110.  
  111. #include <unistd.h>        /* select(); */
  112. #include <sys/time.h>        /* timeval */
  113.  
  114.  
  115. /*
  116.  * This is the mouse handler.
  117.  * It generates integer numbers, to simulate keys
  118.  */
  119.  
  120. int
  121. mouse_handler (Gpm_Event * event, void *unused)
  122. {
  123.     static Region *prevPtr;
  124.     Region *butPtr;
  125.     static int grabkey = 0;
  126.     static int reptkey = 0;
  127.     static int dragging = 0;
  128.     static int prevY;
  129.     static int prevMouseDown;    /* xterm gives only generic up events */
  130.  
  131. #define CURRENT_POS (M_EVENT+event->y-bigRegion.y-1)
  132.  
  133. #if 0
  134.     fprintf (stderr,
  135.          "grab %i, more %i, drag %i, x %i, y %i, butt %i, type %x\n",
  136.          grabkey, gpm_morekeys, dragging, event->x,
  137.          event->y, event->buttons, event->type);
  138. #endif
  139.  
  140.     if (grabkey) {        /* return key or 0 */
  141.     if (Gpm_Repeat (100))
  142.         return grabkey;    /* go on (slow to ease xterm( */
  143.     else
  144.         return grabkey = gpm_morekeys = 0;    /* no more grab */
  145.     }
  146.     if (gpm_morekeys) {        /* repeat a key */
  147.     gpm_morekeys--;
  148.     return reptkey;
  149.     }
  150.     if (dragging) {
  151.     /* respond to motions, independently of where they are */
  152.     int delta;
  153.     if (!(event->type & GPM_DRAG)) {
  154.         dragging--;
  155.         return CURRENT_POS;
  156.     }
  157.     delta = event->y - prevY;
  158.     if (!delta)
  159.         return 0;
  160.     prevY = event->y;
  161.     reptkey = (delta > 0 ? KEY_DOWN : KEY_UP);
  162.     gpm_morekeys = bigRegion.step * abs (delta);
  163.     return (reptkey == KEY_UP ? M_EVENT : M_EVENT + bigRegion.height);
  164.     }
  165.     /* the big region */
  166.  
  167.     if (bigregionFlag &&
  168.     event->y >= bigRegion.y && event->y < bigRegion.Y &&
  169.     event->x >= bigRegion.x && event->x < bigRegion.X) {
  170.     /* top border */
  171.     if (event->y == bigRegion.y) {
  172.         if ((event->type & GPM_DOWN) && (event->buttons & GPM_B_LEFT)) {
  173.         grabkey = KEY_UP;
  174.         gpm_morekeys = 1;
  175.         return KEY_UP;
  176.         } else
  177.         return 0;
  178.     }
  179.     /* bottom border */
  180.     if (event->y + 1 == bigRegion.Y) {
  181.         if ((event->type & GPM_DOWN) && (event->buttons & GPM_B_LEFT)) {
  182.         grabkey = KEY_DOWN;
  183.         gpm_morekeys = 1;
  184.         return KEY_DOWN;
  185.         } else
  186.         return 0;
  187.     }
  188.     /* right half */
  189.     reptkey = 0;
  190.     if (event->x > bigRegion.xth) {
  191.         if (event->type & GPM_DOWN)
  192.         switch (event->buttons) {
  193.         case GPM_B_LEFT:
  194.             reptkey = KEY_DOWN - KEY_UP;
  195.         case GPM_B_RIGHT:
  196.             reptkey += KEY_UP;
  197.             gpm_morekeys = event->y - bigRegion.y;
  198.             return (reptkey == KEY_UP ? M_EVENT
  199.                 : M_EVENT + bigRegion.height);
  200.  
  201.         case GPM_B_MIDDLE:
  202.             prevY = event->y;
  203.             dragging++;
  204.             return 0;
  205.         }
  206.         return CURRENT_POS;
  207.     }
  208.     /* left half */
  209.     else {            /* WARN *//* check down events as well */
  210.         if ((event->type & GPM_UP) && (event->buttons & GPM_B_LEFT)) {
  211.         if (event->type & GPM_SINGLE) {
  212.             reptkey = ' ';
  213.             gpm_morekeys = (bigRegion.mode == 0);
  214.             return M_EVENT + 'o';
  215.         }
  216.         return '\n';
  217.         }
  218.         return CURRENT_POS;
  219.     }
  220.  
  221.     return 0;
  222.     }
  223.     /* smaller regions */
  224.  
  225.     /* retrieve the frame under the pointer */
  226.     for (butPtr = regionList; butPtr; butPtr = butPtr->next) {
  227.     if (event->y < butPtr->y || event->y >= butPtr->Y)
  228.         continue;
  229.     if (event->x < butPtr->x || event->x >= butPtr->X)
  230.         continue;
  231.     break;            /* found */
  232.     }
  233.  
  234.  
  235.     switch (GPM_BARE_EVENTS (event->type)) {
  236.     case GPM_MOVE:
  237.     if (butPtr && butPtr != prevPtr) {    /* enter event */
  238.         prevPtr = butPtr;
  239.         return M_EVENT + butPtr->code;
  240.     }
  241.     break;
  242.  
  243.     case GPM_DRAG:
  244.     if (butPtr && butPtr != prevPtr)    /* enter event (with button) */
  245.         return M_EVENT + butPtr->code;
  246.     break;
  247.  
  248.     case GPM_DOWN:        /* down: remember where */
  249.     prevPtr = butPtr;
  250.     prevMouseDown = event->buttons;        /* to handle xterm b-up event */
  251.     break;
  252.  
  253.     case GPM_UP:        /* WARN multiple presses are bad-behaving */
  254.     switch (prevMouseDown) {    /* event->buttons doesn't run with xterm */
  255.     case GPM_B_RIGHT:
  256.         return '\n';
  257.     case GPM_B_MIDDLE:
  258.         return '\t';
  259.     case GPM_B_LEFT:
  260.  
  261.         if (butPtr && butPtr == prevPtr) {
  262.         /* complete button press *//* return two keys... */
  263.         gpm_morekeys++;
  264.         reptkey = butPtr->code;
  265.         return M_EVENT + toupper (butPtr->code);
  266.         }
  267.         prevPtr = butPtr;
  268.         return M_EVENT + butPtr->code;    /* no, only an enter event */
  269.     }
  270.     }
  271.     return 0;            /* nothing relevant */
  272. }
  273.